Kinetis SDK API Reference Manual  1.0.0-beta
Freescale Semiconductor, Inc.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Groups Pages

The section describes the programming interface of the eDMA Peripheral driver. More...

Data Structures

struct  edma_scatter_list_t
 Data structure for configuring a discrete memory transfer. More...
 
struct  edma_channel_t
 Data structure for the DMA channel. More...
 

Typedefs

typedef void(* edma_callback_t )(void *parameter, edma_channel_status_t status)
 Definition for the DMA channel callback function. More...
 

Enumerations

enum  edma_descriptor_internal_status_t {
  kEdmaDescriptorDone = 0U,
  kEdmaDescriptorPrepared = 0xFFFFFFFFU
}
 Status of the DMA hardware descriptor. More...
 
enum  edma_tcd_alignment_t {
  kEdmaTcdAlignment = 0x20U,
  kEdmaTcdAlignmentMask = 0x1FU
}
 Alignment for eDMA TCD start address. More...
 
enum  edma_channel_type_t {
  kEdmaInvalidChannel = 0xFFU,
  kEdmaAnyChannel = 0xFEU
}
 A constant for the DMA allocation status. More...
 
enum  edma_channel_status_t {
  kEdmaIdle,
  kEdmaNormal,
  kEdmaError
}
 Channel status for an eDMA channel. More...
 
enum  edma_transfer_type_t {
  kEdmaPeripheralToMemory,
  kEdmaMemoryToPeripheral,
  kEdmaMemoryToMemory,
  kEdmaPeripheralToPeripheral
}
 A type for the DMA transfer. More...
 

eDMA Peripheral Driver

edma_status_t edma_init (void)
 Initializes eDMA.
 
edma_status_t edma_shutdown (void)
 De-initilizes eDMA.
 
void edma_register_callback (edma_channel_t *chn, edma_callback_t callback, void *para)
 Registers the callback function and a parameter. More...
 
edma_status_t edma_get_descriptor_status (edma_channel_t *chn, uint32_t *descriptorStatus)
 Gets the status of the eDMA channel descriptor chain. More...
 
uint32_t edma_request_channel (uint32_t channel, dma_request_source_t source, edma_channel_t *chan)
 Requests an eDMA channel. More...
 
edma_status_t edma_free_channel (edma_channel_t *chn)
 Frees eDMA channel hardware and software resource. More...
 
edma_status_t edma_start_channel (edma_channel_t *chn)
 Starts an eDMA channel. More...
 
edma_status_t edma_stop_channel (edma_channel_t *chn)
 Stops an eDMA channel. More...
 
edma_status_t edma_update_descriptor (edma_channel_t *chn)
 Updates the status of a particular descriptor in the eDMA. More...
 
edma_status_t edma_config_loop (edma_software_tcd_t *stcd, edma_channel_t *chn, edma_transfer_type_t type, uint32_t srcAddr, uint32_t destAddr, uint32_t size, uint32_t watermark, uint32_t length, uint8_t period)
 Configures the DMA transfer in a scatter-gather mode. More...
 
edma_status_t edma_config_scatter_gather (edma_software_tcd_t *stcd, edma_channel_t *chn, edma_transfer_type_t type, uint32_t size, uint32_t watermark, edma_scatter_list_t *srcScatterList, edma_scatter_list_t *destScatterList, uint8_t number)
 Configures the DMA transfer in scatter-gather mode. More...
 
void EDMA_IRQ_HANDLER (uint32_t channel)
 eDMA IRQ Handler More...
 
void DMA_ERR_IRQHandler (uint32_t instance)
 eDMA ERROR IRQ Handler More...
 

EDMA PERIPHERAL Driver

Overview

The eDMA driver requests, configures, and uses eDMA hardware. It supports module initializations and DMA channel configurations.

Initialization

To initialize the DMA module, call the edma_init() function. The user does not need to pass a configuration data structure. This function enables the eDMA module and clock automatically.

Channel concept

The eDMA module has many channels. Additionally, the EDMA peripheral driver is designed based on a channel concept. All operations should be started by requesting an eDMA channel and ended by freeing an eDMA channel. The user can configure and run operations on the eDMA module by allocating a channel. If a channel is not allocated, a system error may occur.

DMA request concept

A DMA request is used to trigger an eDMA transfer. The DMA request table is available in chip configuration chapters in each chip reference manual.

Memory allocation and alignment

The eDMA peripheral driver does not allocate any memory dynamically. The user needs to provide the allocated memory pointer for the driver and ensure that the memory is valid. If this is not done, a system error may occur. The user needs to prepare three types of memory:

  1. The handler memory: [edma_channel_t]. The driver must store the status data for each channel and the edma_channel_t is designed for this purpose.
  2. The edma_software_tcd_t. The eDMA supports a TCD chain, which provides either the scatter-gather feature or the loop feature. The eDMA module loads the TCDCs from memory, where TCDs are stored. The user must provide the memory storing software TCDs and the edma_config_scatter_gather() function or the edma_config_loop() function configures the software TCDs.
  3. The status memory. If the user wants to know the status of TCD chains, the user needs to provide the status memory and the driver will fill it with the chain status.
    The start address of the software TCDs must be 32 bytes.

    Call diagram

To use the DMA driver, follow these steps:

  1. Initialize the DMA module: edma_init().
  2. Request a DMA channel: edma_request_channel().
  3. Configure the TCD:
    • Configure the TCD chain in a scatter-gather list. UART transmit/receive is the common case.
    • Configure the TCD chain in a loop way. Audio playback/Record is the common case.
  4. Register callback function: edma_register_callback.
  5. Start the DMA channel: edma_start_channel.
  6. [OPTION] Stop the DMA channel: edma_stop_channel.
  7. Free the DMA channel: edma_free_channel.
This is an example code to initialize and configure the driver by configuring the descriptor:
stcd = (edma_software_tcd_t *)(((uint32_t)status + 32) & ~0x1F);
/* Prepare the memory space. */
for ( i = 0; i < kEdmaTestChainLength; i++)
{
/* Allocate the memory! */
srcAddr[i] = malloc(kEdmaTestBufferSize);
destAddr[i] = malloc(kEdmaTestBufferSize);
/* Check whether the allocation is successfully. */
if (((uint32_t)srcAddr[i] == 0x0U) & ((uint32_t)destAddr[i] == 0x0U))
{
printf("Fali to allocate memory for EDMA test! \r\n");
goto error;
}
/* Init the memory buffer. */
for (j = 0; j < kEdmaTestBufferSize; j++)
{
srcAddr[i][j] = j;
destAddr[i][j] = 0;
}
srcSG[i].address = (uint32_t)srcAddr[i];
destSG[i].address = (uint32_t)destAddr[i];
srcSG[i].length = kEdmaTestBufferSize;
destSG[i].length = kEdmaTestBufferSize;
}
if (edma_request_channel(channel, kDmaRequestMux0AlwaysOn62, &chan_handler) != channel)
{
printf("Failed to request channel %d !\r\n", channel);
goto error;
}
stcd, &chan_handler, kDmaMemoryToMemory,
0x1U, kEdmaTestWatermarkLevel,
srcSG, destSG,
kEdmaTestChainLength);
edma_register_callback(&chan_handler, test_callback, &chan_handler);
edma_start_channel(&chan_handler);
For an example to configure the loop mode, see the SAI module driver.

Extend the driver

The user can call the eDMA HAL driver to extend the application capability.

Data Structure Documentation

struct edma_scatter_list_t

Data Fields

uint32_t address
 Address of buffer. More...
 
uint32_t length
 Length of buffer. More...
 

Field Documentation

uint32_t edma_scatter_list_t::address
uint32_t edma_scatter_list_t::length
struct edma_channel_t

Data Fields

uint8_t module
 eDMA physical module indicator
 
uint8_t channel
 eDMA physical channel indicator
 
uint8_t dmamuxModule
 DMA Mux module indicator. More...
 
uint8_t dmamuxChannel
 DMA Mux channel indicator. More...
 
edma_callback_t callback
 Callback for the eDMA channel. More...
 
void * parameter
 Parameter for the callback function. More...
 
volatile edma_channel_status_t status
 Channel status. More...
 
uint8_t tcdNumber
 Length of the hardware descriptor chain. More...
 
volatile uint8_t tcdWrite
 Indicator for updates of the user descriptor. More...
 
volatile uint8_t tcdRead
 Indicator for the consuming of the DMA controller. More...
 
uint32_t tcdLeftBytes
 Left bytes to be transferred for a current TCD. More...
 
volatile bool tcdUnderflow
 
     Flag indicating whether the user failed to feed a descriptor in

time. More...

 

Field Documentation

uint8_t edma_channel_t::dmamuxModule
uint8_t edma_channel_t::dmamuxChannel
edma_callback_t edma_channel_t::callback
void* edma_channel_t::parameter
volatile edma_channel_status_t edma_channel_t::status
uint8_t edma_channel_t::tcdNumber
volatile uint8_t edma_channel_t::tcdWrite
volatile uint8_t edma_channel_t::tcdRead
uint32_t edma_channel_t::tcdLeftBytes
volatile bool edma_channel_t::tcdUnderflow

Typedef Documentation

typedef void(* edma_callback_t)(void *parameter, edma_channel_status_t status)

Prototype for the callback function registered in the DMA driver.

Enumeration Type Documentation

Defines the status of the DMA descriptor. The status of the descriptor is not limited to these two states. It can also be any the value between 0~0xFFFFFFFF for left bytes of a specified descriptor.

Enumerator
kEdmaDescriptorDone 

The descriptor is finished.

kEdmaDescriptorPrepared 

The descriptor is either consumed or not consumed.

Enumerator
kEdmaTcdAlignment 

Alignment of the eDMA TCD.

kEdmaTcdAlignmentMask 

Alignment mask of the eDMA TCD.

A structure used for the dma_request_channel.

Enumerator
kEdmaInvalidChannel 

Macros indicate the failure of the channel request.

kEdmaAnyChannel 

Macros used when requesting channel.

kEdmaAnyChannel means a request of a dynamic channel allocation.

A structure describing the DMA channel status. The user can get the status from the channel callback function.

Enumerator
kEdmaIdle 

DMA channel is idle.

kEdmaNormal 

DMA channel is occupied.

kEdmaError 

An error occurs in the DMA channel.

Enumerator
kEdmaPeripheralToMemory 

Transfer from peripheral to memory.

kEdmaMemoryToPeripheral 

Transfer from memory to peripheral.

kEdmaMemoryToMemory 

Transfer from memory to memory.

kEdmaPeripheralToPeripheral 

Transfer from peripheral to peripheral.

Function Documentation

void edma_register_callback ( edma_channel_t chn,
edma_callback_t  callback,
void *  para 
)

The user register callback function and parameter for a specified eDMA channel. When channel interrupt or channel error occurs, the callback function is called and a parameter along with user parameter is provided to indicate the channel status.

Parameters
chnHandler for eDMA channel.
callbackCallback function.
paraA parameter for callback functions.
edma_status_t edma_get_descriptor_status ( edma_channel_t chn,
uint32_t *  descriptorStatus 
)

This function indicates the status of descriptor chains. The user needs to provide the memory space to store the descriptor status. A parameter descriptorStatus is the pointer for the descriptorStatus. If the descriptorStaus can't point to a valid memory space and the length of the memory is not enough to store the descriptor status, an error occurs inside the DMA driver. Every descriptor needs a uint32_t to store the status. If the return descriptorStatus[n] is equal to the kEdmaDescriptorPrepared, the descriptor is either consuming or it is already prepared but not consumed. Any other value indicates the left bytes to be transferred for this descriptor. If the value is equal to 0, it means the descriptor is already finished. The user can update the memory for this descriptor safely. To get a precise status of the descriptor, the user can first stop the channel. The ongoing descriptor is updated with a value indicating bytes to be transferred for this descriptor. If not, it indicates that this descriptor is ongoing with a value of kEdmaDescriptorPrepared.

Parameters
chnHandler for eDMA channel.
descriptorStatusStatus of descriptors.
uint32_t edma_request_channel ( uint32_t  channel,
dma_request_source_t  source,
edma_channel_t chan 
)

This function provides two ways to allocate a DMA channel: static allocation and dynamic allocation. To allocate a channel dynamically, the user should set the channel parameter with the value of kDmaAnyChannel. The driver searches all available channels and assigns the first channel to the user. To allocate the channel statically, the user should set the channel parameter with the value of a specified channel. If the channel is available, the driver assigns the channel to the user. Note that the user must provide the handler memory for the DMA channel. The driver initializes the handler and configures the handler memory.

Parameters
channeleDMA channel number. If a channel is assigned with a valid channel number, the DMA driver tries to assign a specified channel to the user. If a channel is assigned with a kDmaAnyChannel, the DMA driver searches all available channels and assigns the first channel to the user.
sourceeDMA hardware request.
chanMemory pointing to eDMA channel. The user must ensure that the handler memory is valid and that it will not be released or changed by another code before the channel is freed.
Returns
If the channel allocation is successful, the return value indicates the requested channel. If not, the driver returns a kDmaInvalidChannel value to indicate that the requested operation has failed.
edma_status_t edma_free_channel ( edma_channel_t chn)

This function frees the relevant software and hardware resources. The request and the freeing operation need to be called in a pair.

Parameters
chnMemory pointing to the eDMA channel
edma_status_t edma_start_channel ( edma_channel_t chn)

Starts an eDMA channel. The driver starts an eDMA channel by enabling the DMA request. The software start bit is not used in the eDMA peripheral driver.

Parameters
chnMemory pointing to the eDMA channel.
edma_status_t edma_stop_channel ( edma_channel_t chn)

This function stops an eDMA channel and updates the descriptor chain status. By calling the edma_get_descriptor_status() function, the ongoing left bytes of the descriptor are updated and the user can simultaneously get the status of all descriptors.

Parameters
chnMemory pointing to the eDMA channel
edma_status_t edma_update_descriptor ( edma_channel_t chn)

This function is designed for the loop descriptor chain. When descriptor is chained in loop mode, the DMA constantly consumes descriptors. At the same time, the user may need to update the content belonging to a consumed descriptor. This function is used to update the descriptor state from "CONSUMED" to "TO BE CONSUMED". In this case, the DMA driver can work out whether the underflow happens on the loop descriptor chain. This function can only update descriptors one-by-one in a sequence but not a specified descriptor.

Parameters
chnMemory pointing to the eDMA channel
edma_status_t edma_config_loop ( edma_software_tcd_t stcd,
edma_channel_t chn,
edma_transfer_type_t  type,
uint32_t  srcAddr,
uint32_t  destAddr,
uint32_t  size,
uint32_t  watermark,
uint32_t  length,
uint8_t  period 
)

This function configures descriptors in a loop chain. The user passes a block of memory into this function. The memory is divided into "period" sub blocks. The DMA driver configures "period" descriptors. Each descriptor stands for a sub block. The DMA driver transfers data from the 1st descriptor to the last descriptor. Then, the DMA driver wraps to the first descriptor to continue the loop. The interrupt handler is called on every finish of a descriptor. The user can find out whether a descriptor is in the process of being transferred, is already transferred, or to be transferred by calling the edma_get_descriptor_status() function in the interrupt handler or any other task context. At the same time, the user can call the edma_update_descriptor() function to tell the DMA driver that the content belonging to a descriptor is already updated and the DMA needs to count it as and underflow next time it loops to this descriptor.

Parameters
chnMemory pointing to the eDMA channel
stcdMemory pointing to software TCDs. The user must prepare this memory block. The required memory size is equal to a "period" * size of(edma_software_tcd_t). At the same time, the "stcd" must align with 32 bytes. If not, an error occurs in the eDMA driver.
srcAddrA source register address or a start memory address.
destAddrA destination register address or a start memory address.
sizeSize to be transferred on every DMA write/read. Source/Dest share the same write/read size.
watermarksize write/read for every trigger of the DMA request.
lengthTotal length of Memory. A number of the descriptor that is configured for this transfer configuration.
edma_status_t edma_config_scatter_gather ( edma_software_tcd_t stcd,
edma_channel_t chn,
edma_transfer_type_t  type,
uint32_t  size,
uint32_t  watermark,
edma_scatter_list_t srcScatterList,
edma_scatter_list_t destScatterList,
uint8_t  number 
)

This function configure descriptors into sing-end chain. User passed blocks of memory into this function. Interrupt will only be triggered on the last memory block is finished. The information of memory blocks are passed by edma_scatter_list_t data structure which can tell the memory address and length. DMA driver will configure descriptor for every memory block and transfer descriptor from the first one to the last one and then stop.

Parameters
chnMemory pointing to eDMA channel.
stcdMemory pointing to software TCDs. The user must prepare this memory block. The required memory size is equal to the "number" * size of(edma_software_tcd_t). At the same time, the "stcd" must align with 32 bytes. If not, an error occurs in the eDMA driver.
typeTransfer type.
srcScatterListData structure storing the address and length to be transferred for source memory blocks. If source memory is peripheral, the length is not used.
destScatterListData structure storing the address and length to be transferred for dest memory blocks. If in the memory-to-memory transfer mode, the user must ensure that the length of the dest scatter gather list is equal to the source scatter gather list. If the dest memory is a peripheral register, the length is not used.
sizeSize to be transferred on each DMA write/read. Source/Dest share the same write/read size.
watermarkSize write/read for each trigger of the DMA request. number A number of memory block contained in the scatter gather list.
void EDMA_IRQ_HANDLER ( uint32_t  channel)
void DMA_ERR_IRQHandler ( uint32_t  instance)